package web.login;

import domain.User;
import exceptions.UserAlreadyExistsException;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.*;
import org.apache.wicket.markup.html.image.Image;
import org.apache.wicket.markup.html.panel.ComponentFeedbackPanel;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.apache.wicket.util.time.Duration;
import org.apache.wicket.validation.IValidatable;
import org.apache.wicket.validation.IValidator;
import org.apache.wicket.validation.ValidationError;
import org.apache.wicket.validation.validator.AbstractValidator;
import org.apache.wicket.validation.validator.EmailAddressValidator;
import org.jasypt.util.password.PasswordEncryptor;
import service.facade.user.UserService;
import web.commons.CaptchaTextField;
import web.commons.MultipleComponentsMessageFilter;
import web.eshop.CaptchaImageModel;

import java.util.logging.Level;
import java.util.logging.Logger;


public class RegistrationForm extends Form<User> {
    @SpringBean
    public UserService userService;
    IModel<User> userModel;
    @SpringBean
    PasswordEncryptor passwordEncryptor;
    private static Logger logger = Logger.getLogger(RegistrationPage.class.getName());
    private String password;
    private String password2;
    private String captchaPassword;
    CaptchaImageModel captchaImageModel = new CaptchaImageModel(5, 6);
    Boolean checkBox;

    public Boolean isCheckBox() {
        return checkBox;
    }

    public void setCheckBox(Boolean checkBox) {
        this.checkBox = checkBox;
    }

    public void setCheckBox(boolean checkBox) {
        this.checkBox = checkBox;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    private String getPassword2() {
        return password2;
    }

    private void setPassword2(String password2) {
        this.password2 = password2;
    }

    private String getCaptchaPassword() {
        return captchaPassword;
    }

    private void setCaptchaPassword(String captchaPassword) {
        this.captchaPassword = captchaPassword;
    }

    public RegistrationForm(String id) {
        super(id, new CompoundPropertyModel<User>(new User()));

        validateComponents();
        validate();
        validateFormValidators();
        setOutputMarkupId(true);

        add(new Image("captchaImage", captchaImageModel));

        WebMarkupContainer container = new WebMarkupContainer("captcha");
        add(container);
        if (WebApplication.DEVELOPMENT.equalsIgnoreCase(WebApplication.get().getConfigurationType())) {
            IModel<String> model = new LoadableDetachableModel<String>() {

                @Override
                protected String load() {
                    return captchaImageModel.getImagePass();
                }
            };
            container.add(new Label("password", model));
        } else {
            container.setVisible(false);
        }

        TextField field = new CaptchaTextField("captchaPassword", new PropertyModel(this, "captchaPassword"));
        field.add(new IValidator<String>() {
            private static final long serialVersionUID = 1L;

            public void validate(IValidatable<String> validatable) {
                if (!captchaImageModel.getImagePass().equals(validatable.getValue())) {
                    validatable.error(new ValidationError().setMessage(getLocalizer().getString("comment.fail.password", RegistrationForm.this)));


                }
            }
        });


        add(field);
        RequiredTextField textField = new RequiredTextField("login");
        textField.setMarkupId("registrationLogin");
        textField.add(new AbstractValidator<String>() {
            private static final long serialVersionUID = 1L;


            @Override
            protected void onValidate(IValidatable<String> validatable) {
                if (userService.findUserByLogin(validatable.getValue()) != null) {
                    validatable.error(new ValidationError().setMessage(getLocalizer().getString("registration.fail.loginExist", RegistrationForm.this)));
                }

            }
        });

        Component feedback = new ComponentFeedbackPanel("feedbackLogin", textField);
        feedback.setOutputMarkupId(true);
        add(feedback);

        OnChangeAjaxBehavior onChangeAjaxBehavior = new OnChangeAjaxBehavior() {
            private static final long serialVersionUID = 1L;

            @Override
            protected void onError(AjaxRequestTarget target, RuntimeException e) {
                Panel feedback = (ComponentFeedbackPanel) get("feedbackLogin");
                target.addComponent(feedback);

            }

            @Override
            protected void onUpdate(AjaxRequestTarget target) {
                Panel feedback = (ComponentFeedbackPanel) get("feedbackLogin");
                target.addComponent(feedback);

            }
        };
        onChangeAjaxBehavior.setThrottleDelay(Duration.seconds(2));
        textField.add(onChangeAjaxBehavior);
        add(textField);

        ///////////////                    password
        IValidator<String> validator = new IValidator<String>() {
            private static final long serialVersionUID = 1L;

            @SuppressWarnings("unchecked")
            public void validate(IValidatable<String> validatable) {
                TextField password = (TextField) get("password");
                TextField password2 = (TextField) get("password2");
//
//                System.out.println("////");
//                System.out.println("1" + password.getValue());
//                System.out.println("2" + password2.getValue());
//                System.out.println("3" + validatable.getValue());
//                System.out.println("4" + getPassword());
//                System.out.println("5" + getPassword2());
//                System.out.println("////");


                if (!password.getValue().equals("") && !password2.getValue().equals("") && !password.getValue().equals(password2.getValue())) {
                    error(validatable);
                }


                //for  getConvertedInput();
                //                if (password2.getConvertedInput() != null) {
//                    setPassword2(password2.getValue());
//                }
//                if (password.getConvertedInput() != null) {
//                    setPassword(password.getValue());
//                }
//                if (password.getValue() == null && getPassword() != null && password2.getValue() != null) {
//                    if (!validatable.getValue().equals(getPassword())) {
//                        error(validatable);
//                    }
//                } else if (password2.getValue() == null && getPassword2() != null && password.getValue() != null) {
//                    if (!validatable.getValue().equals(getPassword2())) {
//                        error(validatable);
//                    }
//                } else {
//                    //hopefully OK
//                }

            }

            private void error(IValidatable<String> validatable) {
                validatable.error(new ValidationError()
                        .setMessage(getLocalizer().getString("registrationForm.passwords.notEqual", RegistrationForm.this)));
            }

        };
        MultipleComponentsMessageFilter messageFilter = new MultipleComponentsMessageFilter();
        feedback = new FeedbackPanel("feedbackPasswordField", messageFilter);
        feedback.setOutputMarkupId(true);
        add(feedback);

        TextField passwordField = new PasswordTextField("password", new PropertyModel(this, "password"));
        passwordField.setMarkupId("registrationPassword");

        passwordField.setOutputMarkupId(true);
        passwordField.add(validator);
        add(passwordField);
        messageFilter.addComponent(passwordField);

        OnChangeAjaxBehavior componentUpdatingBehavior = new OnChangeAjaxBehavior() {
            private static final long serialVersionUID = 1L;


            @Override
            protected void onError(AjaxRequestTarget target, RuntimeException e) {
                Panel feedback = (FeedbackPanel) get("feedbackPasswordField");
                target.addComponent(feedback);

            }

            @Override
            protected void onUpdate(AjaxRequestTarget target) {
                Panel feedback = (FeedbackPanel) get("feedbackPasswordField");
                target.addComponent(feedback);

            }
        };
        passwordField.add(componentUpdatingBehavior);

        passwordField = new PasswordTextField("password2", new PropertyModel(this, "password2"));
        passwordField.setMarkupId("registrationPasswordVerify");

        passwordField.setOutputMarkupId(true);
        add(passwordField);
        messageFilter.addComponent(passwordField);

        componentUpdatingBehavior = new OnChangeAjaxBehavior() {
            private static final long serialVersionUID = 1L;


            @Override
            protected void onError(AjaxRequestTarget target, RuntimeException e) {
                Panel feedback = (FeedbackPanel) get("feedbackPasswordField");
                target.addComponent(feedback);

            }

            @Override
            protected void onUpdate(AjaxRequestTarget target) {
                Panel feedback = (FeedbackPanel) get("feedbackPasswordField");
                target.addComponent(feedback);

            }
        };
        passwordField.add(validator);
        passwordField.add(componentUpdatingBehavior);


        FormComponent mail = new RequiredTextField("companyEmail").add(EmailAddressValidator.getInstance());

        AjaxFormComponentUpdatingBehavior behavior = new AjaxFormComponentUpdatingBehavior("onblur") {

            @Override
            protected void onUpdate(AjaxRequestTarget target) {
                TextField mail = (TextField) get("companyEmail");
                target.addComponent(mail);
            }
        };
        mail.add(behavior);
        add(mail);

        add(new TextField("firstName"));
        add(new TextField("lastName"));

        add(new TextField("tradingName"));
        add(new TextField("tradingName2"));
        add(new TextField("companyID"));
        add(new TextField("taxID"));
        add(new TextField("bankNumber"));
        add(new TextField("phone"));
        add(new TextField("fax"));

        add(new TextField("street"));
        add(new TextField("municipality"));
        add(new TextField("postcode"));
        add(new TextField("country"));

    }


    @Override
    protected void onSubmit() {
        try {
            User user = this.getModelObject();
            user.setPassword(getPassword());
            userService.registration(user);
            getModel().detach();
            getSession().info(getLocalizer().getString("registration.success.registered", this));
            setResponsePage(getApplication().getHomePage());
        } catch (UserAlreadyExistsException ex) {
            error(getLocalizer().getString("registration.fail.loginExist", this));
            logger.log(Level.SEVERE, getLocalizer().getString("registration.fail.loginExist", this), ex);
        } catch (Exception ex) {
            error(getLocalizer().getString("system.error", this));
            logger.log(Level.SEVERE, getModelObject().toString(), ex);
        }
    }

    @Override
    protected void onRender(MarkupStream markupStream) {
        super.onRender(markupStream);
    }
}
